/*
 * @(#)GameBO.java $version 2011. 10. 14
 * 
 * Copyright 2011 NHN Corp. All rights Reserved.
 * NHN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
 */
package com.hangame.mbl.bo.game;

import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;

import net.sf.json.JSONArray;
import net.sf.json.JSONObject;

import org.apache.axis.utils.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.http.HttpStatus;

import com.hangame.mbl.dao.game.GameDAO;
import com.hangame.mbl.model.Game;
import com.hangame.mbl.model.GameGenre;
import com.hangame.mbl.model.GameList;
import com.hangame.mbl.model.GameOsInfo;
import com.hangame.mbl.model.GameSimpleInfo;
import com.hangame.mbl.model.InstallInfo;
import com.hangame.mbl.model.OsInfo;
import com.hangame.mbl.model.ScreenShot;
import com.hangame.mbl.model.Theme;
import com.hangame.mbl.util.HttpClientUtil;
import com.nhncorp.lucy.common.data.DataHandlerFactory;
import com.nhncorp.lucy.web.metadata.Inject;
	
// TODO: Auto-generated Javadoc
/**
 * The Class GameBO.
 *
 * @author NHN
 */
public class GameBO {
	
	/** The Constant LOG. */
	private static final Log LOG = LogFactory.getLog(GameBO.class);
	
	/** The game dao. */
	private GameDAO gameDAO = null;
	
	/** The Constant INSTALL_INFO_URL. */
	private final static String INSTALL_INFO_URL = DataHandlerFactory.getDataHandler().get("url/game_install_info_url");
	
	/** The Constant REDIRECT_URL. */
	private final static String REDIRECT_URL = DataHandlerFactory.getDataHandler().get("url/redirect_url");
	
	/**
	 * Sets the game dao.
	 * 
	 * @param gameDAO the new game dao
	 */
	@Inject(beanId = "gameDAO")
	public void setGameDAO(GameDAO gameDAO) {
		this.gameDAO = gameDAO;
	}

	/**
	 * 해당하는 게임목록 가져오기.
	 * 
	 * @param genreCode the genre code
	 * @param offset the offset
	 * @param count the count
	 * @return the game list
	 * @return
	 */
	public List<GameList> getGameList(String genreCode, int offset, int count) {
		List<GameList> gameList = new ArrayList<GameList>();
		try {
			gameList = gameDAO.selectGameList(genreCode, offset, count, false);
			gameList = getOSYn(gameList);
			if (gameList == null) {
				throw new Exception();
			}
		} catch (Exception e) {
			LOG.error(e, e);
			return new ArrayList<GameList>();
		}

		return gameList;
	}

	/**
	 * 모든 PC 게임 네임 리스트 setAttribute.
	 * 
	 * @return the all game simple list
	 * @return
	 */
	public ArrayList<GameSimpleInfo> getAllGameSimpleList() {
		ArrayList<GameSimpleInfo> allTempGameSimpleList = new ArrayList<GameSimpleInfo>();
		ArrayList<GameSimpleInfo> allGameSimpleList = new ArrayList<GameSimpleInfo>();
		try {
			allTempGameSimpleList = gameDAO.selectAllGameSimpleList();
			if (allTempGameSimpleList == null) {
				throw new Exception();
			}
		} catch (Exception e) {
			LOG.error(e, e);
			return new ArrayList<GameSimpleInfo>();
		}
		
		for (GameSimpleInfo gameInfo : allTempGameSimpleList) {		  
			gameInfo.setGameName(gameInfo.getGameName());
			allGameSimpleList.add(gameInfo);
		}
		
		return allGameSimpleList;
	}

	/**
	 * 모든 게임목록 가져오기.
	 * 
	 * @return the game list
	 * @return
	 */
	public ArrayList<GameList> getGameList() {
		ArrayList<GameList> gameList = new ArrayList<GameList>();
		try {
			gameList = gameDAO.selectGameList("", 0, 0, true);
			if (gameList == null) {
				throw new Exception();
			}
		} catch (Exception e) {
			LOG.error(e, e);
			return new ArrayList<GameList>();
		}

		return gameList;
	}

	/**
	 * 게임목록 총 갯수 가져오기.
	 * 
	 * @param genreCode the genre code
	 * @return the game list count
	 * @return
	 */
	public Integer getGameListCount(String genreCode) {
		Integer count;
		try {
			count = gameDAO.selectGameListCount(genreCode);
			if (count == null) {
				throw new Exception();
			}
		} catch (Exception e) {
			LOG.error("게임목록 갯수 가져오기 실패", e);
			return 0;
		}

		return count;
	}

	/**
	 * Gets the recommend game list.
	 * 
	 * @return the recommend game list
	 */
	public List<GameList> getRecommendGameList() {
		List<GameList> gameList = new ArrayList<GameList>();
		try {
			gameList = gameDAO.selectRecommendGameList();
			gameList = getOSYn(gameList);
			if (gameList == null) {
				throw new Exception();
			}
		} catch (Exception e) {
			LOG.error(e, e);
			return new ArrayList<GameList>();
		}

		return gameList;
	}

	/**
	 * Gets the theme game list.
	 * 
	 * @param themeId the theme id
	 * @param offset the offset
	 * @param count the count
	 * @return the theme game list
	 */
	public List<GameList> getThemeGameList(int themeId, int offset, int count) {
		List<GameList> gameList = new ArrayList<GameList>();
		try {
			gameList = gameDAO.selectThemeGameList(themeId, offset, count);
			gameList = getOSYn(gameList);
			if (gameList == null) {
				throw new Exception();
			}
		} catch (Exception e) {
			LOG.error(e, e);
			return new ArrayList<GameList>();
		}

		return gameList;
	}

	/**
	 * Gets the related game list.
	 * 
	 * @param gameNo the game no
	 * @return the related game list
	 */
	public List<GameList> getRelatedGameList(int gameNo) {
		List<GameList> gameList = new ArrayList<GameList>();
		try {
			gameList = gameDAO.selectRelatedGameList(gameNo);
			gameList = getOSYn(gameList);
			if (gameList == null) {
				throw new Exception();
			}
		} catch (Exception e) {
			LOG.error(e, e);
			return new ArrayList<GameList>();
		}

		return gameList;
	}

	/**
	 * Gets the game detail info.
	 * 
	 * @param gameNo the game no
	 * @return the game detail info
	 */
	public Game getGameDetailInfo(int gameNo) {
		Game gameDetailInfo = new Game();
		try {
			gameDetailInfo = gameDAO.selectGameDetailInfo(gameNo);
			gameDetailInfo.setScreenShotList(getScreenShotList(gameNo));
			gameDetailInfo.setInstallInfoList(getInstallInfoList(gameNo));
			gameDetailInfo.setRelatedGameList(getRelatedGameList(gameNo));
		} catch (Exception e) {
			LOG.error(e, e);
			Game gameTemDetailInfo = new Game();
			gameTemDetailInfo.setGameNo(-1);
			return  gameTemDetailInfo;
		}

		return gameDetailInfo;

	}

	/**
	 * Gets the screen shot list.
	 * 
	 * @param gameNo the game no
	 * @return the screen shot list
	 */
	public List<ScreenShot> getScreenShotList(int gameNo) {
		List<ScreenShot> screenShotList = new ArrayList<ScreenShot>();
		try {
			screenShotList = gameDAO.selectScreenShotList(gameNo);
			if (screenShotList == null) {
				throw new Exception();
			}
		} catch (Exception e) {
			LOG.error(e, e);
			return new ArrayList<ScreenShot>();
		}

		return screenShotList;
	}

	/**
	 * Gets the install info list.
	 * 
	 * @param gameNo the game no
	 * @return the install info list
	 */
	public List<InstallInfo> getInstallInfoList(int gameNo) {
		List<InstallInfo> installInfoList = new ArrayList<InstallInfo>();
		try {
			String[] response = HttpClientUtil.getResponseBodyGet(INSTALL_INFO_URL, "UTF-8", 1000);
			int status = Integer.valueOf(response[0]);
			if (HttpStatus.SC_OK == status) {
				JSONArray gameOsInfoArray = JSONObject.fromObject(response[1]).getJSONArray("installInfoMap");
				for (int i = 0; i < gameOsInfoArray.size(); i++) {
					JSONObject gameOsInfo = gameOsInfoArray.getJSONObject(i);
					JSONArray osInfoList = gameOsInfo.getJSONArray("osInfoList");
					if (gameOsInfo.getInt("gameNo") == gameNo) {
						for (int osInfoIndex = 0; osInfoIndex < osInfoList.size(); osInfoIndex++) {
							InstallInfo installInfo = new InstallInfo();
							installInfo.setOsType(osInfoList.getJSONObject(osInfoIndex).getString("osType"));
							installInfo.setUrl(REDIRECT_URL + gameOsInfo.getInt("gameNo") + "&market=" + osInfoList.getJSONObject(osInfoIndex).getString("marketType") + "&osType=" + osInfoList.getJSONObject(osInfoIndex).getString("osType") + "&deviceType=PC");
							installInfo.setMarket(osInfoList.getJSONObject(osInfoIndex).getString("marketType"));
							installInfo.setInstallImageURL(osInfoList.getJSONObject(osInfoIndex).getString("installImageUrl"));
							
							installInfoList.add(installInfo);
						}
					}
				}
			}
			return installInfoList;
		} catch (Exception e) {
			LOG.error(e, e);
			return new ArrayList<InstallInfo>();
		}
	}

	/**
	 * 게임 장르 한글명 리스트.
	 * 
	 * @return the game gnr list
	 * @return
	 */
	public ArrayList<GameGenre> getGameGnrList() {
		ArrayList<GameGenre> resultList = new ArrayList<GameGenre>();

		try {
			resultList = gameDAO.selectGameGnrList();
			if (resultList == null) {
				throw new Exception();
			}
		} catch (Exception e) {
			LOG.error(e, e);
			return new ArrayList<GameGenre>();
		}

		return resultList;
	}

	/**
	 * 평점 로그 저장하기.
	 * 
	 * @param userId the user id
	 * @param gameNo the game no
	 * @param value the value
	 * @return true, if successful
	 * @return
	 */
	public boolean insertStarRatingLog(String userId, int gameNo, double value) {
		HashMap<String, String> params = new HashMap<String, String>();
		params.put("userId", userId);
		params.put("gameNo", String.valueOf(gameNo));
		params.put("value", String.valueOf(value));

		try {
			gameDAO.insertStarRatingLog(params);
		} catch (Exception e) {
			LOG.error(e, e);
			return false;
		}

		return true;
	}

	/**
	 * Gets the star rating.
	 * 
	 * @param gameNo the game no
	 * @return the star rating
	 */
	public HashMap<String, String> getStarRating(int gameNo) {
		HashMap<String, String> params = new HashMap<String, String>();
		params.put("gameNo", String.valueOf(gameNo));

		HashMap<String, String> result = new HashMap<String, String>();

		try {
			result = gameDAO.selectStarRating(params);
			if (result == null) {
				return new HashMap<String, String>();
			}
		} catch (Exception e) {
			LOG.error(e, e);
			return new HashMap<String, String>();
		}

		return result;
	}

	/**
	 * Insert star rating.
	 * 
	 * @param gameNo the game no
	 * @param value the value
	 * @param avgScore the avg score
	 * @return true, if successful
	 */
	@SuppressWarnings({"rawtypes", "unchecked"})
	public boolean insertStarRating(int gameNo, double value, double avgScore) {
		HashMap params = new HashMap();
		params.put("gameNo", gameNo);
		params.put("value", value);
		params.put("avgScore", value);
		params.put("totScore", value);

		try {
			gameDAO.insertStarRating(params);
		} catch (Exception e) {
			LOG.error(e, e);
			return false;
		}

		return true;
	}

	/**
	 * Update star rating.
	 * 
	 * @param gameNo the game no
	 * @param value the value
	 * @param avgScore the avg score
	 * @return true, if successful
	 */
	@SuppressWarnings({"rawtypes", "unchecked"})
	public boolean updateStarRating(int gameNo, double value, double avgScore) {
		HashMap params = new HashMap();
		params.put("gameNo", gameNo);
		params.put("value", value);
		params.put("avgScore", avgScore);

		try {
			this.gameDAO.updateStarRating(params);
		} catch (Exception e) {
			LOG.error(e, e);
			return false;
		}

		return true;
	}

	/**
	 * Gets the star rating log count by id.
	 * 
	 * @param gameNo the game no
	 * @param userId the user id
	 * @return the star rating log count by id
	 */
	@SuppressWarnings({"rawtypes", "unchecked"})
	public Integer getStarRatingLogCountById(int gameNo, String userId) {
		HashMap params = new HashMap();
		params.put("gameNo", gameNo);
		params.put("userId", userId);

		Integer count = 0;

		try {
			count = this.gameDAO.selectStarRatingLogCountById(params);
			if (count == null) {
				return 0;
			}
		} catch (Exception e) {
			LOG.error(e, e);
			return 0;
		}
		return count;
	}

	/**
	 * Gets the star rating log by id.
	 * 
	 * @param gameNo the game no
	 * @param userId the user id
	 * @return the star rating log by id
	 */
	@SuppressWarnings({"rawtypes", "unchecked"})
	public Float getStarRatingLogById(int gameNo, String userId) {
		HashMap params = new HashMap();
		params.put("gameNo", gameNo);
		params.put("userId", userId);

		Float scr = 0.0f;

		try {
			scr = this.gameDAO.selectStarRatingLogById(params);
			if (scr == null) {
				return 0.0f;
			}
		} catch (Exception e) {
			LOG.error(e, e);
			return 0.0f;
		}
		return scr;
	}
	
	/**
	 * Gets the big scr thumb by small scr thumb.
	 * 
	 * @param sThumbId the s thumb id
	 * @return the big scr thumb by small scr thumb
	 */
	public String getBigScrThumbBySmallScrThumb(int sThumbId) {
		String url;

		try {
			url = this.gameDAO.selectBigScrThumbBySmallScrThumb(sThumbId);
			if (StringUtils.isEmpty(url)) {
				throw new Exception("결과없음");
			}
		} catch (Exception e) {
			LOG.error(e, e);
			return "";
		}

		return url;
	}

	/**
	 * Gets the theme list.
	 * 
	 * @return the theme list
	 */
	public List<Theme> getThemeList() {
		List<Theme> list = new ArrayList<Theme>();
		try {
			list = this.gameDAO.selectThemeList();
			if (list == null) {
				throw new Exception();
			}
			
			int maxSize = list.size();
			if (maxSize < 5) {
				list = new ArrayList<Theme>();
			} else if (maxSize > 5) {
				List<Theme> themelist = new ArrayList<Theme>();
				Random random = new Random();
				int[] randomArray = new int[maxSize];
				
				for (int i = 0; i < randomArray.length; i++) {
					randomArray[i] = i;
				}
				
				for (int i = 0; i < 5; i++) {
					int index = random.nextInt(maxSize);
					int temp = randomArray[i];
					randomArray[i] = randomArray[index];
					randomArray[index] = temp;
				}
				
				for (int i = 0; i < 5; i++) {
					themelist.add(list.get(randomArray[i]));
				}
				return themelist;
			}
			
		} catch (Exception e) {
			LOG.error(e, e);
			return new ArrayList<Theme>();
		}

		return list;
	}

	/**
	 * Gets the theme by theme id.
	 * 
	 * @param themeId the theme id
	 * @return the theme by theme id
	 */
	public Theme getThemeByThemeId(int themeId) {
		Theme result = new Theme();

		try {
			result = this.gameDAO.selectThemeByThemeId(themeId);
			if (result == null) {
				throw new Exception("결과없음");
			}
		} catch (Exception e) {
			LOG.error(e, e);
			return new Theme();
		}

		return result;
	}

	/**
	 * 해당 테마ID에 해당하는 게임목록의 갯수를 return한다.
	 * 
	 * @param themeId the theme id
	 * @return the tot cnt theme game list
	 * @return
	 */
	public Integer getTotCntThemeGameList(int themeId) {
		Integer count = 0;

		try {
			count = this.gameDAO.selectTotCntThemeGameList(themeId);
			if (count == null) {
				return 0;
			}
		} catch (Exception e) {
			LOG.error(e, e);
			return 0;
		}
		return count;
	}
	
	/**
	 * Gets the oS yn.
	 * 
	 * @param gameList the game list
	 * @return the oS yn
	 */
	private List<GameList> getOSYn(List<GameList> gameList) {
		if (gameList == null || gameList.size() == 0) {
			return gameList;
		}
			
		int[] gameNoArray = new int[gameList.size()];
		for (int i = 0; i < gameList.size(); i++) {
			gameNoArray[i] = gameList.get(i).getGameNo();
		}
		
		try {
			List<GameOsInfo> gameOsInfoList = gameDAO.selectGameOsInfo(gameNoArray);
			
			Map<Integer, Map<String, String>> gameOsInfoMap = new HashMap<Integer, Map<String, String>>();
			
			if (gameOsInfoList == null) {
				return gameList;
			}
			
			for (GameOsInfo gameOsInfo : gameOsInfoList) {
				List<OsInfo> osInfoList = gameOsInfo.getOsInfoList();
				Map<String, String> osInfoMap = new HashMap<String, String>();
				for (OsInfo osInfo : osInfoList) {
					osInfoMap.put(osInfo.getOsType(), osInfo.getServiceYn());
				}
				gameOsInfoMap.put(gameOsInfo.getGameNo(), osInfoMap);
			}
			
			for (GameList game : gameList) {
				if (gameOsInfoMap.get(game.getGameNo()) != null && "OPEN".equals(game.getOpenType())) {
					game.setIosYn(gameOsInfoMap.get(game.getGameNo()).get("IOS"));
					game.setAndroidYn(gameOsInfoMap.get(game.getGameNo()).get("ANDROID"));
				}
			}
		} catch (SQLException e) {
			LOG.error("게임 설치 정보 가져오기 데러" + e.getLocalizedMessage());
			return gameList;
		}
		
		return gameList;
	}
	
	/**
	 * Checks if is hangame app open.
	 * 
	 * @return the string
	 */
	public String isHangameAppOpen() {
		String openType = "CLOSE";
		try {
			openType = gameDAO.selectHangameAppOpen();
			if (!"OPEN".equals(openType)) {
				return "CLOSE";
			} else {
				return "OPEN";
			}
		} catch (Exception e) {
			LOG.debug("isangameAppOpen" + e.getLocalizedMessage());
			return openType;
		}
	}
}
